#include "private.h"


#ifdef _WITH_DEVICES_
volatile mml_gpio_regs_t dev_gpio[MML_GPIO_DEV_COUNT];
volatile mml_spi_regs_t dev_spi[MML_SPI_DEV_COUNT];
volatile mml_uart_regs_t dev_uart[MML_UART_DEV_COUNT];
volatile mml_tmr_regs_t dev_tmr[MML_TMR_DEV_COUNT];
#endif /* _WITH_DEVICES_ */

extern unsigned int				usecase_loop;
extern unsigned int				usecase_sema;

// uart cfg
static void uart0_handler(void);
static void uart1_handler(void);


static mml_uart_config_t uart_cfg[]={
	[0] = {	// for uart0
		.baudrate = K_LITE_UART0_DEFAULT_BAUDRATE,
		.data_bits = MML_UART_DATA_TRANSFER_SIZE_8_BITS,
		.flwctrl = MML_UART_HW_FLOW_CTL_DISABLE,
		.parity = MML_UART_PARITY_NONE,
		.parity_mode = MML_UART_PARITY_MODE_ONES,
		.rts_ctl = MML_UART_RTS_IO_LEVEL_LOW,
		.stop_bits = MML_UART_STOPBITS_ONE,
		.handler = (mml_uart_handler_t)uart0_handler,
	},

	[1] = {	// for uart1
		.baudrate = K_LITE_UART0_DEFAULT_BAUDRATE,
		.data_bits = MML_UART_DATA_TRANSFER_SIZE_8_BITS,
		.flwctrl = MML_UART_HW_FLOW_CTL_DISABLE,
		.parity = MML_UART_PARITY_NONE,
		.parity_mode = MML_UART_PARITY_MODE_ONES,
		.rts_ctl = MML_UART_RTS_IO_LEVEL_LOW,
		.stop_bits = MML_UART_STOPBITS_ONE,
		.handler = (mml_uart_handler_t)uart1_handler,
	},
};


/******************************************************************************/
int uart_write_char(const char c)
{
#ifdef MDEBUG
    return mml_uart_write_char(DEBUG_UART, c); 
#else
	//return (unsigned int)c;
	return NO_ERROR;
#endif /* _WITH_DEVICES_ */
}

/******************************************************************************/
void init_interfaces(void)
{
#ifdef _WITH_DEVICES_
	volatile mml_gcr_regs_t				*mml_gcr = (volatile mml_gcr_regs_t*)MML_GCR_IOBASE;

	/** Main interfaces used by Secure ROM code, let's reset'em */
#ifndef _GPIO_RESET_AT_INIT_
	/** GPIOS */
	/** Reset all GPIOs' interface */
	mml_gcr->rstr |= MML_GCR_RSTR_GPIO_MASK;
	/** Wait for GPIOs reset to be done */
	while( MML_GCR_RSTR_GPIO_MASK & mml_gcr->rstr );
	/** No clock for GPIOs */
#endif /* _GPIO_RESET_AT_INIT_ */
#ifndef _UART_RESET_AT_INIT_
	/** UARTS */
	/** Reset all UARTs' interface */
	mml_gcr->rstr |= MML_GCR_RSTR_UARTS_MASK;
	/** Wait for UARTs reset to be done */
	while( MML_GCR_RSTR_UARTS_MASK & mml_gcr->rstr );
	/** Stop clock of each UART. It'll be set independently */
	mml_gcr->perckcn |= ( 1 << MML_PERCKCN_DEV_UART0 );
	mml_gcr->perckcn |= ( 1 << MML_PERCKCN_DEV_UART1 );
#endif /* _UART_RESET_AT_INIT_ */
#ifndef _TIMER_RESET_AT_INIT_
	/** TIMERS */
	/** Reset all TIMERs' interface */
	mml_gcr->rstr |= MML_GCR_RSTR_TIMERS_MASK;
	/** Wait for TIMERs reset to be done */
	while( MML_GCR_RSTR_TIMERS_MASK & mml_gcr->rstr );
	/** Stop clock of each Timer. It'll be set independently */
	mml_gcr->perckcn |= ( 1 << MML_PERCKCN_DEV_T0 );
	mml_gcr->perckcn |= ( 1 << MML_PERCKCN_DEV_T1 );
	mml_gcr->perckcn |= ( 1 << MML_PERCKCN_DEV_T2 );
	mml_gcr->perckcn |= ( 1 << MML_PERCKCN_DEV_T3 );
#endif /* _TIMER_RESET_AT_INIT_ */
#else
	/** Nothing to do right now */
#endif /* _WITH_DEVICES_ */
	/** We're done */
	return;
}

#ifdef _WITH_DEVICES_
static void uart1_handler(void)
{
#ifdef _ECHO_WITH_IRQ_
	register unsigned int		isr;
	volatile mml_uart_regs_t	*reg_uart = (volatile mml_uart_regs_t*)MML_UART1_IOBASE;
	unsigned int chx;
	
	isr = reg_uart->isr;

	if ( !( ( MML_UART_IER_FRAMIE_MASK |\
				MML_UART_IER_PARIE_MASK |\
				MML_UART_IER_SIGIE_MASK |\
				MML_UART_IER_OVERIE_MASK ) & isr ) )
	{
		chx = (unsigned char)reg_uart->dr;
		//mml_uart_write_char(MML_UART_DEV1, (u8)chx);
		//lite_printf("uart1 in: %x\n", chx);

		#if (SHELL_DEBUG > 0)
		#if (DEBUG_UART == MML_UART_DEV1)
		shell_buf_push(chx);
		#endif
		#endif

	}

	mml_uart_interrupt_clear(MML_UART_DEV1, isr);
	mml_uart_interrupt_ack(MML_UART_DEV1);
	
#endif

	return;
}

static void uart0_handler(void)
{
#ifdef _ECHO_WITH_IRQ_
	register unsigned int		isr;
	volatile mml_uart_regs_t	*reg_uart = (volatile mml_uart_regs_t*)MML_UART0_IOBASE;
	unsigned int chx;
	
	isr = reg_uart->isr;

	if ( !( ( MML_UART_IER_FRAMIE_MASK |\
				MML_UART_IER_PARIE_MASK |\
				MML_UART_IER_SIGIE_MASK |\
				MML_UART_IER_OVERIE_MASK ) & isr ) )
	{
		chx = (unsigned char)reg_uart->dr;		
		mml_uart_write_char(MML_UART_DEV0, (u8)chx);
	}

	mml_uart_interrupt_clear(MML_UART_DEV0, isr);
	
	mml_uart_interrupt_ack(MML_UART_DEV0);
#endif 
	
	return;
}

/******************************************************************************/
int config_uart(mml_uart_id_t id)
{
	int	result = COMMON_ERR_UNKNOWN;

	result = mml_uart_init(id, uart_cfg[id]);

#ifdef _ECHO_WITH_IRQ_
	if ( NO_ERROR == result )
	{
		/** Disable interruption */
		result = M_MML_UART_INTERRUPT_DISABLE(id);
		if ( result )
		{
			goto echo_uart_init_out;
		}
		/** Clear all IRQ ... */
		mml_uart_interrupt_clear(id, ( MML_UART_ISR_FRAMIS_MASK |\
													MML_UART_ISR_PARIS_MASK |\
													MML_UART_ISR_SIGIS_MASK |\
													MML_UART_ISR_OVERIS_MASK |\
													MML_UART_ISR_FFRXIS_MASK |\
													MML_UART_ISR_FFTXOIS_MASK |\
													MML_UART_ISR_FFTXHIS_MASK ));
		/** ... set wanted interruption(s) */
		mml_uart_interrupt_set(id, ( MML_UART_IER_FFRXIE_MASK |\
													MML_UART_IER_FRAMIE_MASK |\
													MML_UART_IER_PARIE_MASK |\
													MML_UART_IER_SIGIE_MASK |\
													MML_UART_IER_OVERIE_MASK ));

		M_MML_UART_INTERRUPT_ENABLE(id);

	}
	/** We're done */
echo_uart_init_out:
#else
	/** We're done */
#endif /* _ECHO_WITH_IRQ_ */
	return result;
}

/******************************************************************************/
int config_gpio(void)
{
	mml_gpio_config_t 						gpio_conf;

	gpio_conf.gpio_direction = MML_GPIO_DIR_OUT;
	gpio_conf.gpio_function = MML_GPIO_NORMAL_FUNCTION;
	/** Not relevant */
	gpio_conf.gpio_intr_mode = MML_GPIO_INT_MODE_LEVEL_TRIGGERED;
	/** Not relevant */
	gpio_conf.gpio_intr_polarity = MML_GPIO_INT_POL_RAISING;
	gpio_conf.gpio_pad_config = MML_GPIO_PAD_NORMAL;
	/** We're done */
	return mml_gpio_init(MML_GPIO_DEV2, MML_GPIO2_SDHC_LED_PIN, 1, gpio_conf);
}

/******************************************************************************/
int blink_led(void)
{
	int										result = COMMON_ERR_UNKNOWN;
	register unsigned int 					loop = 0;

	/** Delay */
	for( loop = 0;loop < K_BLINK_LED_ON_MAX_COUNT;loop++ );
	/** On LED */
	result = mml_gpio_write_bit_pattern(MML_GPIO_DEV2, MML_GPIO2_SDHC_LED_PIN, 1, 0x01);
	if ( NO_ERROR == result )
	{
		/** Delay */
		for( loop = 0;loop < K_BLINK_LED_OFF_MAX_COUNT;loop++ );
		/** Off LED */
		result = mml_gpio_write_bit_pattern(MML_GPIO_DEV2, MML_GPIO2_SDHC_LED_PIN, 1, 0x00);
	}
	/** We are done! */
	return result;
}

/******************************************************************************/
void save_all_regsiters(void)
{
	register unsigned int					i;

	/** GPIO */
	for( i = MML_GPIO_DEV_MIN;i < MML_GPIO_DEV_COUNT;i++ )
	{
		/**  */
		switch( i )
		{
			case MML_GPIO_DEV0:
				memcpy_int((unsigned int*)&dev_gpio[i], (unsigned int*)MML_GPIO0_IOBASE, ( sizeof(mml_gpio_regs_t) / 4 ));
				break;
			case MML_GPIO_DEV1:
				memcpy_int((unsigned int*)&dev_gpio[i], (unsigned int*)MML_GPIO1_IOBASE, ( sizeof(mml_gpio_regs_t) / 4 ));
				break;
			case MML_GPIO_DEV2:
				memcpy_int((unsigned int*)&dev_gpio[i], (unsigned int*)MML_GPIO2_IOBASE, ( sizeof(mml_gpio_regs_t) / 4 ));
				break;
			default:
				goto save_all_regsiters_out;
		}
	}
	/** UART */
	for( i = MML_UART_DEV_MIN;i <= MML_UART_DEV_MAX;i++ )
	{
		/**  */
		switch( i )
		{
			case MML_UART_DEV0:
				memcpy_int((unsigned int*)&dev_uart[i], (unsigned int*)MML_UART0_IOBASE, ( sizeof(mml_uart_regs_t) / 4 ));
				break;
			case MML_UART_DEV1:
				memcpy_int((unsigned int*)&dev_uart[i], (unsigned int*)MML_UART1_IOBASE, ( sizeof(mml_uart_regs_t) / 4 ));
				break;
			default:
				goto save_all_regsiters_out;
		}
	}
	/** TIMER */
	for( i = MML_TMR_DEV_MIN;i < MML_TMR_DEV_COUNT;i++ )
	{
		/**  */
		switch( i )
		{
			case MML_TMR_DEV0:
				memcpy_int((unsigned int*)&dev_tmr[i], (unsigned int*)MML_TMR0_IOBASE, ( sizeof(mml_tmr_regs_t) / 4 ));
				break;
			case MML_TMR_DEV1:
				memcpy_int((unsigned int*)&dev_tmr[i], (unsigned int*)MML_TMR1_IOBASE, ( sizeof(mml_tmr_regs_t) / 4 ));
				break;
			case MML_TMR_DEV2:
				memcpy_int((unsigned int*)&dev_tmr[i], (unsigned int*)MML_TMR2_IOBASE, ( sizeof(mml_tmr_regs_t) / 4 ));
				break;
		}
	}
	/** SPI */
	for( i = MML_SPI_DEV_MIN;i <= MML_SPI_DEV_MAX;i++ )
	{
		/**  */
		switch( i )
		{
			case MML_SPI_DEV0:
				memcpy_int((unsigned int*)&dev_spi[i], (unsigned int*)MML_SPI0_IOBASE, ( sizeof(mml_spi_regs_t) / 4 ));
				break;
			case MML_SPI_DEV1:
				memcpy_int((unsigned int*)&dev_spi[i], (unsigned int*)MML_SPI1_IOBASE, ( sizeof(mml_spi_regs_t) / 4 ));
				break;
			case MML_SPI_DEV2:
				memcpy_int((unsigned int*)&dev_spi[i], (unsigned int*)MML_SPI2_IOBASE, ( sizeof(mml_spi_regs_t) / 4 ));
				break;
			default:
				goto save_all_regsiters_out;
		}
	}
	/** We're done */
save_all_regsiters_out:
	return;
}

/******************************************************************************/
int display_gpio_registers(void)
{
//	register unsigned int					i;

	/**  */
	lite_printf("\n\tGPIOs registers:\r\n");
	/**  */
#if 0
	for( i = MML_GPIO_DEV_MIN;i < MML_GPIO_DEV_COUNT;i++ )
	{
		/**  */
		lite_printf("\t\tGPIO%d\n",i);
		/**  */
		lite_printf("\t\t\tEN: 0x%08x\n",dev_gpio[i].en);
		lite_printf("\t\t\tEN_SET: 0x%08x\n",dev_gpio[i].en_set);
		lite_printf("\t\t\tEN_CLR: 0x%08x\n",dev_gpio[i].en_clr);
		lite_printf("\t\t\tOUT_EN: 0x%08x\n",dev_gpio[i].out_en);
		lite_printf("\t\t\tOUT_EN_SET: 0x%08x\n",dev_gpio[i].out_en_set);
		lite_printf("\t\t\tOUT_EN_CLR: 0x%08x\n",dev_gpio[i].out_en_clr);
		lite_printf("\t\t\tOUT: 0x%08x\n",dev_gpio[i].out);
		lite_printf("\t\t\tOUT_SET: 0x%08x\n",dev_gpio[i].out_set);
		lite_printf("\t\t\tOUT_CLR: 0x%08x\n",dev_gpio[i].out_clr);
		lite_printf("\t\t\tIN: 0x%08x\n",dev_gpio[i].in);
		lite_printf("\t\t\tINT_MOD: 0x%08x\n",dev_gpio[i].int_mod);
		lite_printf("\t\t\tINT_POL: 0x%08x\n",dev_gpio[i].int_pol);
		lite_printf("\t\t\tINT_EN: 0x%08x\n",dev_gpio[i].int_en);
		lite_printf("\t\t\tINT_EN_SET: 0x%08x\n",dev_gpio[i].int_en_set);
		lite_printf("\t\t\tINT_EN_CLR: 0x%08x\n",dev_gpio[i].int_en_clr);
		lite_printf("\t\t\tINT_STAT: 0x%08x\n",dev_gpio[i].int_stat);
		lite_printf("\t\t\tINT_CLR: 0x%08x\n",dev_gpio[i].int_clr);
		lite_printf("\t\t\tWAKE_EN: 0x%08x\n",dev_gpio[i].wake_en);
		lite_printf("\t\t\tOPEN_DRAIN_EN: 0x%08x\n",dev_gpio[i].open_drain_en);
		lite_printf("\t\t\tINT_DUAL_EDGE: 0x%08x\n",dev_gpio[i].int_dual_edge);
		lite_printf("\t\t\tPAD_CFG1: 0x%08x\n",dev_gpio[i].pad_cfg1);
		lite_printf("\t\t\tPAS_CFG2: 0x%08x\n",dev_gpio[i].pad_cfg2);
		lite_printf("\t\t\tEN1: 0x%08x\n",dev_gpio[i].en1);
		lite_printf("\t\t\tEN1_SET: 0x%08x\n",dev_gpio[i].en1_set);
		lite_printf("\t\t\tEN1_CLR: 0x%08x\n",dev_gpio[i].en1_clr);
	}
#endif
	/** We're done */
	return NO_ERROR;
}

/******************************************************************************/
int display_uart_registers(void)
{
	register unsigned int					i;

	/**  */
	lite_printf("\n\tUARTs registers:\r\n");
	/**  */
	for( i = MML_UART_DEV_MIN;i <= MML_UART_DEV_MAX;i++ )
	{
		/**  */
		lite_printf("\t\tUART%d\r\n",i);
		lite_printf("\t\t\tCR: 0x%08x\r\n", dev_uart[i].cr);
		lite_printf("\t\t\tSR: 0x%08x\r\n", dev_uart[i].sr);
		lite_printf("\t\t\tIER: 0x%08x\r\n", dev_uart[i].ier);
		lite_printf("\t\t\tISR: 0x%08x\r\n", dev_uart[i].isr);
		lite_printf("\t\t\tBRR: 0x%08x\r\n", dev_uart[i].brr);
		lite_printf("\t\t\tRCR: 0x%08x\r\n", dev_uart[i].rcr);
		lite_printf("\t\t\tTXR: 0x%08x\r\n", dev_uart[i].txr);
		lite_printf("\t\t\tPNR: 0x%08x\r\n", dev_uart[i].pnr);
		lite_printf("\t\t\tDR: 0x%08x\r\n", dev_uart[i].dr);
	}
	/** We're done */
	return NO_ERROR;
}

/******************************************************************************/
int display_tmr_registers(void)
{
	register unsigned int					i;

	/**  */
	lite_printf("\n\tTIMERs registers:\r\n");
	/**  */
	for( i = MML_TMR_DEV_MIN;i < MML_TMR_DEV_COUNT;i++ )
	{
		/**  */
		lite_printf("\t\tTIMER%d\r\n",i);
		lite_printf("\t\t\tCOUNT: 0x%08x\r\n", dev_tmr[i].count);
		lite_printf("\t\t\tCOMPARE: 0x%08x\r\n", dev_tmr[i].compare);
		lite_printf("\t\t\tPWM: 0x%08x\r\n", dev_tmr[i].pwm);
		lite_printf("\t\t\tINTERRUPT: 0x%08x\r\n", dev_tmr[i].interrupt);
		lite_printf("\t\t\tCONTROL: 0x%08x\r\n", dev_tmr[i].control);
	}
	/** We're done */
	return NO_ERROR;
}

/******************************************************************************/
int display_spi_registers(void)
{
	register unsigned int					i;

	/**  */
	lite_printf("\n\tSPIs registers:\r\n");
	/**  */
	for( i = MML_SPI_DEV_MIN;i <= MML_SPI_DEV_MAX;i++ )
	{
		/**  */
		lite_printf("\t\tSPI%d\r\n",i);
		lite_printf("\t\t\tDR: 0x%08x\r\n", dev_spi[i].dr);
		lite_printf("\t\t\tCR: 0x%08x\r\n", dev_spi[i].cr);
		lite_printf("\t\t\tSR: 0x%08x\r\n", dev_spi[i].sr);
		lite_printf("\t\t\tMR: 0x%08x\r\n", dev_spi[i].mr);
		lite_printf("\t\t\tDSR: 0x%08x\r\n", dev_spi[i].dsr);
		lite_printf("\t\t\tBRR: 0x%08x\r\n", dev_spi[i].brr);
		lite_printf("\t\t\tDMAR: 0x%08x\r\n", dev_spi[i].dmar);
		lite_printf("\t\t\tI2S_CR: 0x%08x\r\n", dev_spi[i].i2s_cr);
	}
	/** We're done */
	return NO_ERROR;
}

/******************************************************************************/
int reset_all_interfaces(void)
{
#ifdef _DUMMY_CODE_
	int										result = COMMON_ERR_UNKNOWN;

	/** GPIOs */
	result = mml_gpio_reset_interface();
	if ( result )
	{
		goto reset_all_interfaces_out;
	}
	/** UARTs */
	result = mml_uart_reset_interface();
	if ( result )
	{
		goto reset_all_interfaces_out;
	}
	/** TIMERs */
	result = mml_tmr_reset_interface();
	if ( result )
	{
		goto reset_all_interfaces_out;
	}
	/** We're done */
reset_all_interfaces_out:
	return result;
#else
	return NO_ERROR;
#endif /* _DUMMY_CODE_ */
}
#endif /* _WITH_DEVICES_ */

/******************************************************************************/
void memcpy_int(unsigned int *p_dst, unsigned int *p_src, unsigned int size)
{
	register unsigned int					i;

	for( i = 0;i < size;i++ )
	{
		p_dst[i] = p_src[i];
	}
	/** We're done */
	return;
}

/******************************************************************************/
void usecase_timeout_handler(void)
{
	/** Increment loop counter */
	usecase_loop++;
	/** Release semaphore */
	usecase_sema = FALSE;
	/** Clear interruption */
	mml_tmr_interrupt_clear(MML_TMR_DEV0);
	/** Disable timer */
	mml_tmr_disable(MML_TMR_DEV0);
	/** We're done */
	return;
}


/******************************************************************************/
/* EOF */
